
#include <cassert>
#include <cstdlib>

#include <DXGI.h>
#include <D3D10_1.h>
#include <D3DX11.h>

#include "Core\VertexBuffer.h"


VertexBuffer::VertexBuffer(LPCVOID data, UINT size, UINT count)
	: m_data(NULL),
	  m_size(size),
	  m_count(count),
	  m_buffer(NULL),
	  m_binded(FALSE)
{
	m_data = new BYTE[size * count];
	assert(m_data);

	memcpy(m_data, data, size * count);
}


VertexBuffer::~VertexBuffer()
{
	// Unbind if needed.
	if(m_binded)
		Unbind();

	// Free system data.
	if(m_data)
	{
		delete[] m_data;
		m_data = NULL;
	}
}


BOOL VertexBuffer::IsBinded() const
{
	return m_binded;
}


BOOL VertexBuffer::Bind()
{
	assert(!m_binded);

	// Initialize the vertex buffer description.
	D3D11_BUFFER_DESC description;

	description.ByteWidth = m_size * m_count;
	description.Usage = D3D11_USAGE_DEFAULT;
	description.BindFlags = D3D11_BIND_VERTEX_BUFFER;
	description.CPUAccessFlags = 0;
	description.MiscFlags = 0;
	description.StructureByteStride = 0;

	// Initialize the vertex buffer data.
	D3D11_SUBRESOURCE_DATA data;

	data.pSysMem = m_data;
	data.SysMemPitch = 0;
	data.SysMemSlicePitch = 0;

	// Create the vertex buffer.
	HRESULT result = GetDevice()->CreateBuffer(&description, &data, &m_buffer);
	assert(SUCCEEDED(result));

	// Change state to binded.
	m_binded = TRUE;

	return TRUE;
}


VOID VertexBuffer::Unbind()
{
	assert(m_binded);
	
	// Unbind.
	m_buffer->Release();
	m_buffer = NULL;

	// Change state to unbinded.
	m_binded = FALSE;
}


VOID VertexBuffer::Enable()
{
	assert(m_binded);

	// Enable.
	UINT stride = m_size;
	UINT offset = 0;
    
	GetContext()->IASetVertexBuffers(0, 1, &m_buffer, &stride, &offset);
}